package com.pe.pgn.clubpgn.dao.impl;

import java.util.Calendar;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.pe.pgn.clubpgn.common.CLPConstantes;
import com.pe.pgn.clubpgn.dao.PromocionPuntosDao;
import com.pe.pgn.clubpgn.dao.hibernate.GenericDaoHibernate;
import com.pe.pgn.clubpgn.domain.ClpbEstacion;
import com.pe.pgn.clubpgn.domain.ClpmPeriodoPromocion;
import com.pe.pgn.clubpgn.domain.ClpmPromocionEstacion;
import com.pe.pgn.clubpgn.domain.ClpmPromocionPuntos;
import com.pe.pgn.clubpgn.domain.ClpmRangoPromocion;
import com.pe.pgn.clubpgn.domain.beans.BNPromocionEstacion;
import com.pe.pgn.clubpgn.webapp.util.CalendarUtil;

/**
 * @author Edwin Farfan
 */
@Repository("promocionPuntosDao")
public class PromocionPuntosDaoImpl extends GenericDaoHibernate<ClpmPromocionPuntos, Long> implements PromocionPuntosDao{

	JdbcTemplate jdbcTemplate;
	
	@Autowired
	public void setDataSource(DataSource dataSource) {
		this.jdbcTemplate = new JdbcTemplate(dataSource);
		}
	
	public PromocionPuntosDaoImpl() {
		super(ClpmPromocionPuntos.class);
	}	
	
	@SuppressWarnings("unchecked")
	public List<ClpmPromocionPuntos> obtenerPromocionesPuntos() {
		Criteria criteria = DetachedCriteria.forClass(ClpmPromocionPuntos.class)
			.getExecutableCriteria(getSessionFactory().getCurrentSession());
		
			criteria.setMaxResults(CLPConstantes.MAXIMO_RESULTADO_INICIAL);
			criteria.add(Restrictions.eq("stPromocionPuntos", Boolean.TRUE));
			criteria.addOrder(Order.desc("id"));
			 
		return (List<ClpmPromocionPuntos>) criteria.list();
	}

	@SuppressWarnings("unchecked")
	public List<ClpmPromocionPuntos> busquedaPromocionesPuntos(String fechaInicio,
			String fechaFin,String periodo){

		StringBuffer query= new StringBuffer();
		
		query.append(" select promo.id as id, ");   
		query.append(" to_char(promo.da_fecha_inicio,'"+CLPConstantes.DATE_PATTERN+"') as fechaInicio, ");
		query.append(" to_char(promo.da_fecha_fin,'"+CLPConstantes.DATE_PATTERN+"') as fechaFin,  ");
		query.append(" promo.de_promocion_puntos as dePromocionPuntos, ");
		query.append(" periodo.de_periodo_promocion as periodoPromocion ");
		query.append(" from clpm_promocion_puntos   promo ");
		query.append(" left join clpm_periodo_promocion periodo on periodo.id= promo.CO_PERIODO_PROMOCION ");
		query.append(" where  ");   
		query.append(" st_promocion_puntos='"+CLPConstantes.ST_VERDADERO+"' ");
		query.append(" and to_date(da_fecha_inicio) >= to_date('"+fechaInicio+"','"+CLPConstantes.DATE_PATTERN+"') ");
		query.append(" and to_date(da_fecha_fin) <= to_date('"+fechaFin+"','"+CLPConstantes.DATE_PATTERN+"')	 ");
		
		List<ClpmPromocionPuntos> listaPromociones= findListOfBeans(query.toString(), null, ClpmPromocionPuntos.class);
		return listaPromociones;	
	}
	
	
	public ClpmPromocionPuntos obtenerPromocionPuntos(Long id){
		
		ClpmPromocionPuntos promocion= get(id);
		
		promocion.setFechaInicio(CalendarUtil.calendarToString(CLPConstantes.DATE_PATTERN, promocion.getDaFechaInicio()));
		promocion.setFechaFin(CalendarUtil.calendarToString(CLPConstantes.DATE_PATTERN, promocion.getDaFechaFin()));
		
		promocion.setPeriodoPromocion(String.valueOf(promocion.getClpmPeriodoPromocion().getId()));
		
			if(promocion.getDaFechaInicioPeriodo()!=null)
				promocion.setFechaInicioPeriodo(CalendarUtil.calendarToString(CLPConstantes.DATE_PATTERN, promocion.getDaFechaInicioPeriodo()));
				
			if(promocion.getDaFechaFinPeriodo()!=null)
				promocion.setFechaFinPeriodo(CalendarUtil.calendarToString(CLPConstantes.DATE_PATTERN, promocion.getDaFechaFinPeriodo()));
		
		return promocion;
	}
	
	@SuppressWarnings("unchecked")
	public boolean eliminarPromocionPuntos(Long id){
		
		//no se puede eliminar promocion si es que esta vigente
		if(vigenciaPromocion(id)){
			return false;
		}
		
		ClpmPromocionPuntos promocionPuntos= get(id);
		promocionPuntos.setStPromocionPuntos(Boolean.FALSE);
		promocionPuntos.setCoUsuarioModificador(getUsuarioLogueado().getUsername());
		promocionPuntos.setDaFechaModificacion(Calendar.getInstance());
		getHibernateTemplate().update(promocionPuntos);
		
		//Desactivar los rangos de la promocion que se quiere eliminar, ojo solamente se desactivan
		Criteria criteriaRango = DetachedCriteria.forClass(ClpmRangoPromocion.class)
		.getExecutableCriteria(getSessionFactory().getCurrentSession());
		criteriaRango.add(Restrictions.eq("clpmPromocionPuntos", promocionPuntos));
		List<ClpmRangoPromocion> listadoRangoPromocion=criteriaRango.list();
		
		if(!listadoRangoPromocion.isEmpty()){
			for (ClpmRangoPromocion clpmRangoPromocion : listadoRangoPromocion) {
				clpmRangoPromocion.setStRangoPromocion(Boolean.FALSE);
			}
			getHibernateTemplate().saveOrUpdateAll(listadoRangoPromocion);
		}
          
		Criteria criteriaPromocionEstacion = DetachedCriteria.forClass(ClpmPromocionEstacion.class)
		.getExecutableCriteria(getSessionFactory().getCurrentSession());
		criteriaPromocionEstacion.add(Restrictions.eq("clpmPromocionPuntos", promocionPuntos));
		List<ClpmPromocionEstacion> listadoPromocionEstacion=criteriaPromocionEstacion.list();
		
		if(!listadoPromocionEstacion.isEmpty()){
			for (ClpmPromocionEstacion clpmPromocionEstacion : listadoPromocionEstacion) {
				clpmPromocionEstacion.setStPromocionEstacion(Boolean.FALSE);
			}
			getHibernateTemplate().saveOrUpdateAll(listadoPromocionEstacion);
		}
		
		getHibernateTemplate().flush();
		return true;
	}
	
	public void guardarPromocionPuntos(ClpmPromocionPuntos promocionPuntos) {
		
		if(promocionPuntos.getId() == null){
			promocionPuntos.setCoUsuarioCreador(getUsuarioLogueado().getUsername());
			promocionPuntos.setDaFechaCreacion(Calendar.getInstance());
		}
		else{
			promocionPuntos.setCoUsuarioModificador(getUsuarioLogueado().getUsername());
			promocionPuntos.setDaFechaModificacion(Calendar.getInstance());
		}
		try {
			promocionPuntos.setDaFechaInicio(CalendarUtil.stringToCalendar(CLPConstantes.DATE_PATTERN,promocionPuntos.getFechaInicio()));
			promocionPuntos.setDaFechaFin(CalendarUtil.stringToCalendar(CLPConstantes.DATE_PATTERN,promocionPuntos.getFechaFin()));
			
			if(StringUtils.isNotBlank(promocionPuntos.getFechaInicioPeriodo()))
				promocionPuntos.setDaFechaInicioPeriodo(CalendarUtil.stringToCalendar(CLPConstantes.DATE_PATTERN,promocionPuntos.getFechaInicioPeriodo()));
			
			if(StringUtils.isNotBlank(promocionPuntos.getFechaFinPeriodo()))
				promocionPuntos.setDaFechaFinPeriodo(CalendarUtil.stringToCalendar(CLPConstantes.DATE_PATTERN,promocionPuntos.getFechaFinPeriodo()));
			
			//Guardar la promocion de puntos
			promocionPuntos.setStPromocionPuntos(Boolean.TRUE);
	
			getHibernateTemplate().saveOrUpdate(promocionPuntos);
			getHibernateTemplate().flush();
		
			guardarDiasPromocion(promocionPuntos); 
		} catch (Exception e) {
			log.info("info de la excepcion: "+e.getMessage());
		}
	}

	@SuppressWarnings("unchecked")
	public List<ClpmPeriodoPromocion> listadoPeriodosPromocion(){
		Criteria criteria = DetachedCriteria.forClass(ClpmPeriodoPromocion.class)
		.getExecutableCriteria(getSessionFactory().getCurrentSession());
	
		criteria.add(Restrictions.eq("stPeriodoPromocion", Boolean.TRUE));
		criteria.addOrder(Order.asc("id"));
	
         return (List<ClpmPeriodoPromocion>) criteria.list();
	 }
	
	public ClpmPeriodoPromocion obtenerPeriodoPromocion(Long id){
		Criteria criteria = DetachedCriteria.forClass(ClpmPeriodoPromocion.class)
		.getExecutableCriteria(getSessionFactory().getCurrentSession());
		criteria.add(Restrictions.eq("id", id));
		
		return (ClpmPeriodoPromocion)criteria.uniqueResult();
	}
	
	@SuppressWarnings("unchecked")
	public List<BNPromocionEstacion> listadoPromocionEstacion(Long id){

		StringBuffer query= new StringBuffer();
		
		query.append(" select estacion.id as id, "); 
		query.append(" estacion.co_codigo_cofide as codigoCofide, "); 
		query.append(" estacion.de_estacion as deEstacion, ");
		query.append(" 'Y' as stPromocionEstacion, ");
		query.append(" promoestacion.co_estacion as clpbEstacion, "); 
		query.append(" promoestacion.id as promocionEstacion ");
		query.append(" from clpb_estacion estacion ");
		query.append(" join clpm_promocion_estacion promoestacion ");
		query.append(" on estacion.id=promoestacion.co_estacion ");
		query.append(" where  ");
		query.append(" estacion.st_estacion='"+CLPConstantes.ST_VERDADERO+"' ");
		query.append(" and promoestacion.co_promocion_puntos= "+id);
		query.append(" union ");
		query.append(" select estacion.id as id, "); 
		query.append(" estacion.co_codigo_cofide as codigoCofide, "); 
		query.append(" estacion.de_estacion as deEstacion, ");
		query.append(" 'N' as stPromocionEstacion, ");
		query.append(" promoestacion.co_estacion as clpbEstacion, "); 
		query.append(" promoestacion.id as promocionEstacion ");
		query.append(" from clpb_estacion estacion ");
		query.append(" left join clpm_promocion_estacion promoestacion ");
		query.append(" on (estacion.id=promoestacion.co_estacion and promoestacion.co_promocion_puntos="+id+") ");
		query.append(" where  ");
		query.append(" estacion.st_estacion='"+CLPConstantes.ST_VERDADERO+"' ");
		query.append(" and estacion.id not in ");
		query.append(" (select estacion.id from clpb_estacion estacion ");
		query.append(" join clpm_promocion_estacion promoest  on estacion.id=promoest.co_estacion  ");
		query.append(" where   estacion.st_estacion='"+CLPConstantes.ST_VERDADERO+"'  and promoest.co_promocion_puntos= "+id+")");
		
		
		return findListOfBeans(query.toString(), null, BNPromocionEstacion.class);
	 }
	
	@SuppressWarnings("unchecked")
	public List<ClpbEstacion> listadoEstaciones(){
		Criteria criteria = DetachedCriteria.forClass(ClpbEstacion.class)
		.getExecutableCriteria(getSessionFactory().getCurrentSession());
	
		criteria.add(Restrictions.eq("stEstacion", Boolean.TRUE));
		criteria.addOrder(Order.desc("id"));
	
         return (List<ClpbEstacion>) criteria.list();
	 }
	
	public void modificarEstacionPromocion(String []estacion,String promocionPuntos,
			String [] checkbox,String [] idPromocionEstacion, Integer filas){
		
		for (int i = 0; i < filas; i++) {
			
			log.info("Agregar Estacion idEstacion:  "+estacion[i]);
			log.info("Agregar Estacion idPromocionPuntos:  "+promocionPuntos);
			log.info("Agregar Estacion checkbox:  "+checkbox[i]);
			log.info("Agregar Estacion idPromocionEstacion:  "+idPromocionEstacion[i]);
			
			ClpmPromocionEstacion promocionEstacion=getHibernateTemplate().get(ClpmPromocionEstacion.class, new Long(idPromocionEstacion[i]));
			Boolean flatCheck=new Boolean(checkbox[i]);
			
			if(promocionEstacion==null){
				if(flatCheck){
					promocionEstacion=new ClpmPromocionEstacion();
					promocionEstacion.setStPromocionEstacion(Boolean.TRUE);
					promocionEstacion.setCoUsuarioCreador(getUsuarioLogueado().getUsername());
					promocionEstacion.setDaFechaCreacion(Calendar.getInstance());
					promocionEstacion.setClpmPromocionPuntos(getHibernateTemplate().get(ClpmPromocionPuntos.class, new Long(promocionPuntos)));
					promocionEstacion.setClpbEstacion(getHibernateTemplate().get(ClpbEstacion.class, new Long(estacion[i])));
					//Agregar una nueva Promocion de estacion 
					getHibernateTemplate().save(promocionEstacion);
					getHibernateTemplate().flush();
				}		
			}else{
				if(!flatCheck){
					//Elimina una promocion estacion
					getHibernateTemplate().delete(promocionEstacion);
					getHibernateTemplate().flush();
				}
			}	
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<ClpmRangoPromocion> listarRangoPromocion(Long id){
			//El id es de la promocion
		StringBuffer query=new StringBuffer();
		query.append(" select ");
		query.append(" id as id, ");
		query.append(" va_cantidad_fin as vaCantidadFin, ");
		query.append(" va_cantidad_inicio as vaCantidadInicio, ");
		query.append(" va_factor as vaFactor, ");
		query.append(" va_sumando as vaSumando  ");
		query.append(" from clpm_rango_promocion"); 
		query.append(" where co_promocion_puntos="+id);
		query.append(" and st_rango_promocion='"+CLPConstantes.ST_VERDADERO+"'");
		
        return findListOfBeans(query.toString(), null, ClpmRangoPromocion.class);	
		
	}
	
	public void guardarRangos(String idPromocionPuntos, String cantidadInicio,String cantidadFin,String factor, String sumando){
		
		ClpmRangoPromocion rangoPromocion=new ClpmRangoPromocion();
		
		if(rangoPromocion.getId() == null){
			rangoPromocion.setCoUsuarioCreador(getUsuarioLogueado().getUsername());
			rangoPromocion.setDaFechaCreacion(Calendar.getInstance());
		}
		else{
			rangoPromocion.setCoUsuarioCreador(getUsuarioLogueado().getUsername());
			rangoPromocion.setDaFechaModificacion(Calendar.getInstance());
		}
		
		rangoPromocion.setStRangoPromocion(Boolean.TRUE);
		
		if(StringUtils.isNotBlank(idPromocionPuntos))
			rangoPromocion.setClpmPromocionPuntos(getHibernateTemplate().get(ClpmPromocionPuntos.class, new Long(idPromocionPuntos)));
			
		if(StringUtils.isNotBlank(cantidadInicio))	
			rangoPromocion.setVaCantidadInicio(Integer.parseInt(cantidadInicio));
		
		if(StringUtils.isNotBlank(cantidadFin))
			rangoPromocion.setVaCantidadFin(Integer.parseInt(cantidadFin));
		
		if(StringUtils.isNotBlank(factor))
			rangoPromocion.setVaFactor(Integer.parseInt(factor));
		
		if(StringUtils.isNotBlank(sumando))
			rangoPromocion.setVaSumando(Integer.parseInt(sumando));
			
		getHibernateTemplate().saveOrUpdate(rangoPromocion);
		getHibernateTemplate().flush();		
	}
	
	public void eliminarRangos(String idRangoPromocion){
		
		ClpmRangoPromocion promocionPuntos=getHibernateTemplate().get(ClpmRangoPromocion.class, new Long(idRangoPromocion));
		
		promocionPuntos.setStRangoPromocion(Boolean.FALSE);
		getHibernateTemplate().update(promocionPuntos);
		getHibernateTemplate().flush();
	}

	
	public void guardarDiasPromocion(ClpmPromocionPuntos promocionPuntos) {

		Boolean lunes		= promocionPuntos.getVaLunes()!=null?promocionPuntos.getVaLunes():Boolean.TRUE;
		Boolean martes		= promocionPuntos.getVaMartes()!=null?promocionPuntos.getVaMartes():Boolean.TRUE;
		Boolean miercoles	= promocionPuntos.getVaMiercoles()!=null?promocionPuntos.getVaMiercoles():Boolean.TRUE;
		Boolean jueves		= promocionPuntos.getVaJueves()!=null?promocionPuntos.getVaJueves():Boolean.TRUE;
		Boolean viernes		= promocionPuntos.getVaViernes()!=null?promocionPuntos.getVaViernes():Boolean.TRUE;
		Boolean sabado		= promocionPuntos.getVaSabado()!=null?promocionPuntos.getVaSabado():Boolean.TRUE;
		Boolean domingo		= promocionPuntos.getVaDomingo()!=null?promocionPuntos.getVaDomingo():Boolean.TRUE;
		
		Integer periodo= Integer.parseInt(promocionPuntos.getPeriodoPromocion());
		if (periodo ==3){
			lunes = Boolean.TRUE;
			martes= Boolean.TRUE;
			miercoles = Boolean.TRUE;
			jueves = Boolean.TRUE;
			viernes = Boolean.TRUE;
			sabado	= Boolean.FALSE;
			domingo	= Boolean.FALSE;
		}else if (periodo ==4){
			lunes = Boolean.TRUE;
			martes= Boolean.FALSE;
			miercoles= Boolean.TRUE;
			jueves = Boolean.FALSE;
			viernes = Boolean.TRUE;
			sabado	= Boolean.FALSE;
			domingo	= Boolean.FALSE;
		}else if(periodo ==5){
			lunes = Boolean.FALSE;
			martes= Boolean.TRUE;
			miercoles= Boolean.FALSE;
			jueves = Boolean.TRUE;
			viernes = Boolean.FALSE;
			sabado	= Boolean.FALSE;
			domingo	= Boolean.FALSE;
		}
		
		promocionPuntos.setVaLunes(lunes);
		promocionPuntos.setVaMartes(martes);
		promocionPuntos.setVaMiercoles(miercoles);
		promocionPuntos.setVaJueves(jueves);
		promocionPuntos.setVaViernes(viernes);
		promocionPuntos.setVaSabado(sabado);
		promocionPuntos.setVaDomingo(domingo);
	
	}
	
	
	public boolean vigenciaPromocion(Long id){
		
		StringBuffer query= new StringBuffer();
		
		query.append(" select pp.* from clpm_promocion_puntos pp");
		query.append(" left join clpm_dias_promocion pd on pp.id = pd.co_promocion_puntos");
		query.append(" where pp.st_promocion_puntos='"+CLPConstantes.ST_VERDADERO+"'");
		query.append(" and pd.st_dias_promocion = '"+CLPConstantes.ST_VERDADERO+"'");
		
		query.append(" and ((to_date(to_char(pp.da_fecha_inicio, 'dd/MM/yyyy'),'dd/MM/yyyy') " +
        "<= to_date(to_char(sysdate, 'dd/MM/yyyy'),'dd/MM/yyyy') ");
		query.append(" and to_date(to_char(pd.da_fecha_fin_periodo, 'dd/MM/yyyy'),'dd/MM/yyyy') " +
        ">= to_date(to_char(sysdate, 'dd/MM/yyyy'),'dd/MM/yyyy')) or pd.da_fecha_fin_periodo is null) ");
		
		query.append(" and pp.id="+id);
		
		List<Map<String, Object>> promocionVigente= jdbcTemplate.queryForList(query.toString());
		
		if(promocionVigente.isEmpty()){
			return false;
		}
		return true;
	}
	
	public boolean translapePromocion(ClpmPromocionPuntos pActual) throws Exception{

		List<ClpmPromocionPuntos> listaPromociones= obtenerPromocionesPuntos();
		
		pActual.setDaFechaInicio(CalendarUtil.stringToCalendar(CLPConstantes.DATE_PATTERN,pActual.getFechaInicio()));
		pActual.setDaFechaFin(CalendarUtil.stringToCalendar(CLPConstantes.DATE_PATTERN,pActual.getFechaFin()));
		
		for (ClpmPromocionPuntos promo : listaPromociones) {
			
			boolean rangoFechas = (promo.getDaFechaInicio().before(pActual.getDaFechaInicio())) 
								&& (pActual.getDaFechaFin().before(promo.getDaFechaFin()));
			
			boolean periodoIgual = (promo.getClpmPeriodoPromocion().getId() == Long.parseLong(pActual.getPeriodoPromocion()));
			
			if(!pActual.getPeriodoPromocion().equals("0")){
				
				if(periodoIgual && pActual.getTodoDia() == true){
					return true;
				}
				else if(rangoFechas && pActual.getTodoDia() == true){
					return true;
				}
				else if(rangoFechas){
					
					String [] horaIni= promo.getDaHoraInicio().split(":");
					String [] horaFin= promo.getDaHoraFin().split(":");
					
					String [] pActualHoraIni= pActual.getDaHoraInicio().split(":");
					String [] pActualHoraFin= pActual.getDaHoraFin().split(":");
					
					boolean rangoHora1 = (Integer.parseInt(pActualHoraIni[0]) >= Integer.parseInt(horaIni[0])) &&
					(Integer.parseInt(pActualHoraFin[0]) <= Integer.parseInt(horaFin[0]));
					
					if(rangoHora1){
						return true;
					}
				}
			}
			
		} 
		return false;
	}
	
	public void eliminarRangoByPromocion(Long idPromocion){
		
		StringBuffer query= new StringBuffer();
		query.append(" delete from clpm_rango_promocion ");
		query.append(" where st_rango_promocion= '"+CLPConstantes.ST_VERDADERO+"' ");
		query.append(" and co_promocion_puntos="+new Long(idPromocion));

		jdbcTemplate.update(query.toString());
	}
}

